/**
 * Copyright (c) 2011-2014, James Zhan 詹波 (jfinal@126.com).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */

package com.jfinal.weixin.demo;

import java.io.IOException;
import java.util.Collections;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.jfinal.kit.PropKit;
import com.jfinal.weixin.sdk.api.ApiConfig;
import com.jfinal.weixin.sdk.jfinal.MsgController;
import com.jfinal.weixin.sdk.msg.in.InImageMsg;
import com.jfinal.weixin.sdk.msg.in.InLinkMsg;
import com.jfinal.weixin.sdk.msg.in.InLocationMsg;
import com.jfinal.weixin.sdk.msg.in.InTextMsg;
import com.jfinal.weixin.sdk.msg.in.InVideoMsg;
import com.jfinal.weixin.sdk.msg.in.InVoiceMsg;
import com.jfinal.weixin.sdk.msg.in.event.InFollowEvent;
import com.jfinal.weixin.sdk.msg.in.event.InLocationEvent;
import com.jfinal.weixin.sdk.msg.in.event.InMenuEvent;
import com.jfinal.weixin.sdk.msg.in.event.InQrCodeEvent;
import com.jfinal.weixin.sdk.msg.in.speech_recognition.InSpeechRecognitionResults;
import com.jfinal.weixin.sdk.msg.out.OutImageMsg;
import com.jfinal.weixin.sdk.msg.out.OutNewsMsg;
import com.jfinal.weixin.sdk.msg.out.OutTextMsg;
import com.jfinal.weixin.sdk.msg.out.OutVoiceMsg;

/**
 * 将此 DemoController 在YourJFinalConfig 中注册路由， 并设置好weixin开发者中心的 URL 与 token ，使
 * URL 指向该 DemoController 继承自父类 WeixinController 的 index
 * 方法即可直接运行看效果，在此基础之上修改相关的方法即可进行实际项目开发
 */
public class WeixinMsgController extends MsgController {

	private static final String helpStr = "\t发送 help 可获得帮助，发送 \"美女\" 可看美女，发送 news 可看新闻，发送 music 可听音乐，发送历史上的今天还可以查看历史上的今天发生了什么事！！！另外你还可以试试发送图片、语音、位置等信息，看会有什么 。公众号持续更新中，想要更多惊喜欢迎每天关注”帅气小健哥“ ^_^";

	/**
	 * 如果要支持多公众账号，只需要在此返回各个公众号对应的 ApiConfig 对象即可 可以通过在请求 url 中挂参数来动态从数据库中获取
	 * ApiConfig 属性值
	 */
	public ApiConfig getApiConfig() {
		ApiConfig ac = new ApiConfig();

		// 配置微信 API 相关常量
		ac.setToken(PropKit.get("token"));
		ac.setAppId(PropKit.get("appId"));
		ac.setAppSecret(PropKit.get("appSecret"));

		/**
		 * 是否对消息进行加密，对应于微信平台的消息加解密方式： 1：true进行加密且必须配置 encodingAesKey
		 * 2：false采用明文模式，同时也支持混合模式
		 */
		ac.setEncryptMessage(PropKit.getBoolean("encryptMessage", false));
		ac.setEncodingAesKey(PropKit.get("encodingAesKey",
				"setting it in config file"));
		return ac;
	}

	/**
	 * 实现父类抽方法，处理文本消息 本例子中根据消息中的不同文本内容分别做出了不同的响应，同时也是为了测试 jfinal weixin
	 * sdk的基本功能： 本方法仅测试了 OutTextMsg、OutNewsMsg、OutMusicMsg 三种类型的OutMsg，
	 * 其它类型的消息会在随后的方法中进行测试
	 */
	protected void processInTextMsg(InTextMsg inTextMsg) {
		String msgContent = inTextMsg.getContent().trim();
		// 帮助提示
		if ("help".equalsIgnoreCase(msgContent)) {
			OutTextMsg outMsg = new OutTextMsg(inTextMsg);
			outMsg.setContent(helpStr);
			render(outMsg);
		}

		else if ("news".equalsIgnoreCase(msgContent)) {
			OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
			outMsg
					.addNews(
							"腾讯新闻",
							"腾讯新闻欢迎您！！！！",
							"http://images.cnblogs.com/cnblogs_com/dyg540/269081/o_qq-logo.jpg",
							"http://news.qq.com/");
			render(outMsg);
		}

		else if ("美女".equalsIgnoreCase(msgContent)) {
			OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
			outMsg
					.addNews(
							"我们只看美女",
							"又一大波美女来袭，我们只看美女 ^_^",
							"http://a.hiphotos.baidu.com/image/h%3D300/sign=0039857d50e736d147138a08ab514ffc/241f95cad1c8a786712081af6309c93d70cf500d.jpg",
							"http://image.baidu.com/i?tn=baiduimage&ct=201326592&lm=-1&cl=2&word=%C3%C0%C5%AE%CD%BC%C6%AC&fr=ala&ala=1&alatpl=cover&pos=0#z=0&pn=&ic=0&st=-1&face=0&s=0&lm=-1");
			// outMsg.addNews("秀色可餐", "JFinal Weixin 极速开发就是这么爽，有木有 ^_^",
			// "http://mmbiz.qpic.cn/mmbiz/zz3Q6WSrzq2GJLC60ECD7rE7n1cvKWRNFvOyib4KGdic3N5APUWf4ia3LLPxJrtyIYRx93aPNkDtib3ADvdaBXmZJg/0",
			// "http://mp.weixin.qq.com/s?__biz=MjM5ODAwOTU3Mg==&mid=200987822&idx=1&sn=7eb2918275fb0fa7b520768854fb7b80#rd");

			render(outMsg);
		}
		// 下面实现历史上的今天 TODO
		else if ("历史上的今天".equals(msgContent)) {
			OutTextMsg outMsg = new OutTextMsg(inTextMsg);// 这里有问题，需要把inTextMsg传入
			String content = "历史上的今天 \n";
			// 具体当天的信息
			// 这里通过 JFinal提供的HttpKit爬取历史上的今天网站首页内容
			// String result = HttpKit.get("http://www.lssdjt.com/");
			// System.out.println(result);
			// 观察网站的 布局和设置 发现 div class="main" 里面包含有需要的 历史事件
			// 下面使用jsoup 爬取 并操作DOM，类似jquery
			String url = "http://www.lssdjt.com/";
			try {
				Document doc = Jsoup.connect(url).get();// 这一步和刚才httpkit那个类似，只不过返回的DOM
				if (doc != null) {
					// 获取class=main 下面的所有内容
					Elements elements = doc.getElementsByAttributeValue(
							"class", "main");
					// dom下面的html格式是 ul li a
					// 首先遍历elements
					for (Element element : elements) {
						// System.out.println(element.html());
						// 拿到ul下面li class=gong 下面 所有的 a标签元素 就成功了
						// 使用jquery选择的话是 $("ul li.gong a"),jsoup类似
						Elements elements2 = element.select("ul li.gong");
						// TODO 按理说，现在工作已经完成了，但是微信对文本长度有字数限制，超限的话需要发送会无法响应。
						// 爬虫抽取的数据太多，下面只选择倒序的五条数据即可
						// 首先将dom集合 elements2转成list，并倒序
						List<Element> eList = elements2.subList(0, elements2
								.size());
						Collections.reverse(eList);// 集合倒序
						// 保留至多5条数据，长度小于等于5全部保留
						List<Element> eList2 = eList.subList(0,
								(eList.size() > 10 ? 10 : eList.size()));
						// 遍歷也需要修改一下 elements2改為eList2
						// 同样遍历循环获取所有的信息
						for (Element element2 : eList2) {
							// 这和jquery很像 html()方法获取标签内文本
							// System.out.println(element2.html());
							// 过滤掉 em 和 i 标签就可以了
							String date = element2.select("a em").html();
							String thing = element2.select("i").html();
							String link = element2.select("a").attr("href");
							System.out.println(link);
							content += (date + " " + thing + "  " + link + "\n\n");
						}
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
				content += "网络异常，请稍候再试...";
			}
			outMsg.setContent(content);
			render(outMsg);

		}
		// 其它文本消息直接返回原值 + 帮助提示
		else {
			// TODO 获取用户当前的会话状态(fromusername就是用戶的openid,唯一)
			User user = User.dao.findById(inTextMsg.getFromUserName());
			// 音乐消息测试
			if ("music".equalsIgnoreCase(msgContent)) {
				// TODO 这里处理music 1.张国荣 换行 2.陈奕迅 换行。。。提示用户：请输入歌手名称编号 1 2 3 4
				// TODO 如果用戶沒有記錄，就添加，有的話就更新
				if (user == null) {
					new User().set("userid", inTextMsg.getFromUserName()).set(
							"condition", "music")// 会话状态标示为music
							.save();
				} else {// 更新
					// (這裡做更新是爲了與以後的天氣、公交等接口區別，天氣公交等的處理也是這個思路)
					user.set("condition", "music").update();
				}
				OutTextMsg outMsg = new OutTextMsg(inTextMsg);
				outMsg
						.setContent(" 1.张国荣\n 2.陈奕迅 \n 3.张学友 \n 4.刘德华\n 5.王杰\n 6.汪峰\n 7.谭咏麟\n 8.齐秦\n 9.周华健\n 10.周杰伦\n 回复相应歌手编号 1 2 3...点击即可收听");
				render(outMsg);
			} else {// TODO 如果不是music的话，判断用户当前的会话状态
				String condition = user == null ? "" : user.getStr("condition");
				if ("music".equals(condition)) {// 用户当前是要接收music
					if ("1".equals(msgContent)) {
						OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
						outMsg
								.addNews(
										"张国荣",
										"往事不要再提，人生已多风雨",
										"http://t10.baidu.com/it/u=1765002600,416918645&fm=58",
										"http://music.baidu.com/artist/1092?pst=sug/");
						render(outMsg);
					} else if ("2".equals(msgContent)) {
						OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
						outMsg
								.addNews(
										"陈奕迅",
										"你会不会突然的出现？ ",
										"http://a.hiphotos.baidu.com/ting/pic/item/0dd7912397dda144df7fa1cbb0b7d0a20cf48651.jpg",
										"http://music.baidu.com/artist/1077?pst=sug/");
						render(outMsg);
					} else if ("3".equals(msgContent)) {
						OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
						outMsg
								.addNews(
										"张学友",
										" 想和你再去吹吹风",
										"http://b.hiphotos.baidu.com/ting/pic/item/7dd98d1001e93901115af23b79ec54e736d1965e.jpg",
										"http://music.baidu.com/artist/2507?pst=sug/");
						render(outMsg);
					} else if ("4".equals(msgContent)) {
						OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
						outMsg
								.addNews(
										"刘德华",
										"尽管分开千里仍然怀念你",
										"http://t11.baidu.com/it/u=784498927,1549761800&fm=58",
										"http://music.baidu.com/artist/1224?pst=sug/");
						render(outMsg);
					} else if ("5".equals(msgContent)) {
						OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
						outMsg
								.addNews(
										"王杰",
										"一场游戏一场梦",
										"http://b.hiphotos.baidu.com/ting/pic/item/7af40ad162d9f2d380105ceaabec8a136327ccb6.jpg",
										"http://music.baidu.com/search?key=%E7%8E%8B%E6%9D%B0");
						render(outMsg);
					} else if ("6".equals(msgContent)) {
						OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
						outMsg
								.addNews(
										"汪峰",
										"至少有十年我不曾流泪",
										"http://c.hiphotos.baidu.com/ting/pic/item/b3fb43166d224f4acd880c160bf790529822d1a6.jpg",
										"http://music.baidu.com/artist/1157?pst=sug");
						render(outMsg);
					} else if ("7".equals(msgContent)) {
						OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
						outMsg
								.addNews(
										"谭咏麟",
										"如果果痴痴的等某日终于可等到我心中所爱",
										"http://a.hiphotos.baidu.com/ting/pic/item/03087bf40ad162d920fb061913dfa9ec8a13cd9a.jpg",
										"http://music.baidu.com/search?key=%E8%B0%AD%E5%92%8F%E9%BA%9F");
						render(outMsg);
					} else if ("8".equals(msgContent)) {
						OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
						outMsg
								.addNews(
										"齐秦",
										"给我一个空间，没有人走过",
										"http://musicdata.baidu.com/data2/pic/109772580/109772580.jpg",
										"http://music.baidu.com/artist/1117?pst=sug");
						render(outMsg);
					} else if ("9".equals(msgContent)) {
						OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
						outMsg
								.addNews(
										"周华健",
										"有没有那么一首歌会让你轻轻跟着和",
										"http://c.hiphotos.baidu.com/ting/pic/item/e850352ac65c10384694b1c7b0119313b17e89c8.jpg",
										"http://music.baidu.com/artist/1097?pst=sug");
						render(outMsg);
					} else if ("10".equals(msgContent)) {
						OutNewsMsg outMsg = new OutNewsMsg(inTextMsg);
						outMsg
								.addNews(
										"周杰伦",
										"看不见你的笑我怎么睡得着",
										"http://musicdata.baidu.com/data2/pic/115327437/115327437.jpg",
										"http://music.baidu.com/artist/7994?pst=sug");
						render(outMsg);
					} else {
							OutTextMsg outMsg = new OutTextMsg(inTextMsg);
							outMsg
									.setContent("\t想要了解更多歌手歌曲请持续关注帅气小健哥的每日更新!!! ");
							render(outMsg);
						
					}

				} else {
					OutTextMsg outMsg = new OutTextMsg(inTextMsg);
					outMsg.setContent("\t文本消息已成功接收，您输入的内容为： "
							+ inTextMsg.getContent() + "\n\n" + helpStr);
					render(outMsg);
				}
			}

		}
	}

	/**
	 * 实现父类抽方法，处理图片消息
	 */
	protected void processInImageMsg(InImageMsg inImageMsg) {
		OutImageMsg outMsg = new OutImageMsg(inImageMsg);
		// 将刚发过来的图片再发回去
		outMsg.setMediaId(inImageMsg.getMediaId());
		render(outMsg);
	}

	/**
	 * 实现父类抽方法，处理语音消息
	 */
	protected void processInVoiceMsg(InVoiceMsg inVoiceMsg) {
		OutVoiceMsg outMsg = new OutVoiceMsg(inVoiceMsg);
		// 将刚发过来的语音再发回去
		outMsg.setMediaId(inVoiceMsg.getMediaId());
		render(outMsg);
	}

	/**
	 * 实现父类抽方法，处理视频消息
	 */
	protected void processInVideoMsg(InVideoMsg inVideoMsg) {
		/*
		 * 腾讯 api 有 bug，无法回复视频消息，暂时回复文本消息代码测试 OutVideoMsg outMsg = new
		 * OutVideoMsg(inVideoMsg); outMsg.setTitle("OutVideoMsg 发送");
		 * outMsg.setDescription("刚刚发来的视频再发回去"); // 将刚发过来的视频再发回去，经测试证明是腾讯官方的 api
		 * 有 bug，待 api bug 却除后再试 outMsg.setMediaId(inVideoMsg.getMediaId());
		 * render(outMsg);
		 */
		OutTextMsg outMsg = new OutTextMsg(inVideoMsg);
		outMsg.setContent("\t视频消息已成功接收，该视频的 mediaId 为: "
				+ inVideoMsg.getMediaId());
		render(outMsg);
	}

	/**
	 * 实现父类抽方法，处理地址位置消息
	 */
	protected void processInLocationMsg(InLocationMsg inLocationMsg) {
		OutTextMsg outMsg = new OutTextMsg(inLocationMsg);
		outMsg.setContent("已收到地理位置消息:" + "\nlocation_X = "
				+ inLocationMsg.getLocation_X() + "\nlocation_Y = "
				+ inLocationMsg.getLocation_Y() + "\nscale = "
				+ inLocationMsg.getScale() + "\nlabel = "
				+ inLocationMsg.getLabel());
		render(outMsg);
	}

	/**
	 * 实现父类抽方法，处理链接消息 特别注意：测试时需要发送我的收藏中的曾经收藏过的图文消息，直接发送链接地址会当做文本消息来发送
	 */
	protected void processInLinkMsg(InLinkMsg inLinkMsg) {
		OutNewsMsg outMsg = new OutNewsMsg(inLinkMsg);
		outMsg
				.addNews(
						"链接消息已成功接收",
						"链接使用图文消息的方式发回给你，还可以使用文本方式发回。点击图文消息可跳转到链接地址页面)",
						"http://mmbiz.qpic.cn/mmbiz/zz3Q6WSrzq1ibBkhSA1BibMuMxLuHIvUfiaGsK7CC4kIzeh178IYSHbYQ5eg9tVxgEcbegAu22Qhwgl5IhZFWWXUw/0",
						inLinkMsg.getUrl());
		render(outMsg);
	}

	/**
	 * 实现父类抽方法，处理关注/取消关注消息
	 */
	protected void processInFollowEvent(InFollowEvent inFollowEvent) {
		OutTextMsg outMsg = new OutTextMsg(inFollowEvent);
		outMsg.setContent("欢迎关注帅气小健哥的微信订阅号: \n\n\n " + helpStr);
		// 如果为取消关注事件，将无法接收到传回的信息
		render(outMsg);
	}

	/**
	 * 实现父类抽方法，处理扫描带参数二维码事件
	 */
	protected void processInQrCodeEvent(InQrCodeEvent inQrCodeEvent) {
		OutTextMsg outMsg = new OutTextMsg(inQrCodeEvent);
		outMsg.setContent("processInQrCodeEvent() 方法测试成功");
		render(outMsg);
	}

	/**
	 * 实现父类抽方法，处理上报地理位置事件
	 */
	protected void processInLocationEvent(InLocationEvent inLocationEvent) {
		OutTextMsg outMsg = new OutTextMsg(inLocationEvent);
		outMsg.setContent("processInLocationEvent() 方法测试成功");
		render(outMsg);
	}

	/**
	 * 实现父类抽方法，处理自定义菜单事件
	 */
	protected void processInMenuEvent(InMenuEvent inMenuEvent) {
		renderOutTextMsg("processInMenuEvent() 方法测试成功");
	}

	/**
	 * 实现父类抽方法，处理接收语音识别结果
	 */
	protected void processInSpeechRecognitionResults(
			InSpeechRecognitionResults inSpeechRecognitionResults) {
		renderOutTextMsg("语音识别结果： "
				+ inSpeechRecognitionResults.getRecognition());
	}

}